/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.util;

import cn.easyplatform.EntityNotFoundException;
import cn.easyplatform.contexts.RecordContext;
import cn.easyplatform.dos.UserDo;
import cn.easyplatform.entities.BaseEntity;
import cn.easyplatform.entities.EntityInfo;
import cn.easyplatform.entities.beans.LogicBean;
import cn.easyplatform.entities.beans.ResourceBean;
import cn.easyplatform.entities.beans.api.ApiBean;
import cn.easyplatform.entities.beans.api.Input;
import cn.easyplatform.entities.beans.api.Output;
import cn.easyplatform.entities.beans.page.PageBean;
import cn.easyplatform.entities.beans.project.*;
import cn.easyplatform.entities.beans.table.TableBean;
import cn.easyplatform.entities.beans.table.TableField;
import cn.easyplatform.entities.beans.task.TaskBean;
import cn.easyplatform.entities.transform.TransformerFactory;
import cn.easyplatform.interceptor.CommandContext;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.lang.stream.StringOutputStream;
import cn.easyplatform.messages.vos.addon.TableFieldVo;
import cn.easyplatform.messages.vos.addon.TableVo;
import cn.easyplatform.messages.vos.admin.*;
import cn.easyplatform.type.EntityType;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.util.*;

import static cn.easyplatform.type.Constants.*;


/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public final class EntityUtils {

    /**
     * @param cc
     * @param task
     * @return
     */
    public final static TaskBean getInheritTask(CommandContext cc, RecordContext rc, TaskBean task) {
        if (!Strings.isBlank(task.getInheritId())) {
            task = task.clone();
            String taskId = task.getInheritId();
            if (taskId.startsWith("$")) {
                if (rc == null)
                    return task;
                taskId = (String) rc.getValue(taskId.substring(1));
                task.setInheritId(taskId);
            }
            TaskBean inherit = cc.getEntity(task.getInheritId());
            if (inherit != null) {
                TaskBean superBean = null;
                // init
                if (task.getOnInit() == null) {
                    if (inherit.getOnInit() != null)
                        task.setOnInit(inherit.getOnInit());
                    else if (!Strings.isBlank(inherit.getInheritId())) {
                        superBean = getInheritTask(cc, rc, inherit);
                        if (superBean != null && superBean.getOnInit() != null)
                            task.setOnInit(superBean.getOnInit());
                    }
                }
                // before commit
                if (task.getOnBeforeCommit() == null) {
                    if (inherit.getOnBeforeCommit() != null)
                        task.setOnBeforeCommit(inherit.getOnBeforeCommit());
                    else if (!Strings.isBlank(inherit.getInheritId())) {
                        if (superBean == null)
                            superBean = getInheritTask(cc, rc, inherit);
                        if (superBean != null
                                && superBean.getOnBeforeCommit() != null)
                            task.setOnBeforeCommit(superBean
                                    .getOnBeforeCommit());
                    }
                }
                // after commit
                if (task.getOnAfterCommit() == null) {
                    if (inherit.getOnAfterCommit() != null)
                        task.setOnAfterCommit(inherit.getOnAfterCommit());
                    else if (!Strings.isBlank(inherit.getInheritId())) {
                        if (superBean == null)
                            superBean = getInheritTask(cc, rc, inherit);
                        if (superBean != null
                                && superBean.getOnAfterCommit() != null)
                            task.setOnAfterCommit(superBean.getOnAfterCommit());
                    }
                }
                // rollback
                if (task.getOnRollback() == null) {
                    if (inherit.getOnRollback() != null)
                        task.setOnRollback(inherit.getOnRollback());
                    else if (!Strings.isBlank(inherit.getInheritId())) {
                        if (superBean == null)
                            superBean = getInheritTask(cc, rc, inherit);
                        if (superBean != null
                                && superBean.getOnRollback() != null)
                            task.setOnRollback(superBean.getOnRollback());
                    }
                }
                // committed
                if (task.getOnCommitted() == null) {
                    if (inherit.getOnCommitted() != null)
                        task.setOnCommitted(inherit.getOnCommitted());
                    else if (!Strings.isBlank(inherit.getInheritId())) {
                        if (superBean == null)
                            superBean = getInheritTask(cc, rc, inherit);
                        if (superBean != null
                                && superBean.getOnCommitted() != null)
                            task.setOnCommitted(superBean.getOnCommitted());
                    }
                }
                // committed rollback
                if (task.getOnCommittedRollback() == null) {
                    if (inherit.getOnCommittedRollback() != null)
                        task.setOnCommittedRollback(inherit
                                .getOnCommittedRollback());
                    else if (!Strings.isBlank(inherit.getInheritId())) {
                        if (superBean == null)
                            superBean = getInheritTask(cc, rc, inherit);
                        if (superBean != null
                                && superBean.getOnCommittedRollback() != null)
                            task.setOnCommittedRollback(superBean
                                    .getOnCommittedRollback());
                    }
                }
                // pre commit
                if (task.getOnPreCommit() == null) {
                    if (inherit.getOnPreCommit() != null)
                        task.setOnPreCommit(inherit.getOnPreCommit());
                    else if (!Strings.isBlank(inherit.getInheritId())) {
                        if (superBean == null)
                            superBean = getInheritTask(cc, rc, inherit);
                        if (superBean != null
                                && superBean.getOnPreCommit() != null)
                            task.setOnPreCommit(superBean.getOnPreCommit());
                    }
                }
                // pre commit rollback
                if (task.getOnPreCommitRollback() == null) {
                    if (inherit.getOnPreCommitRollback() != null)
                        task.setOnPreCommitRollback(inherit
                                .getOnPreCommitRollback());
                    else if (!Strings.isBlank(inherit.getInheritId())) {
                        if (superBean == null)
                            superBean = getInheritTask(cc, rc, inherit);
                        if (superBean != null
                                && superBean.getOnPreCommitRollback() != null)
                            task.setOnPreCommitRollback(superBean
                                    .getOnPreCommitRollback());
                    }
                }
                // close
                if (task.getOnClose() == null) {
                    if (inherit.getOnClose() != null)
                        task.setOnClose(inherit.getOnClose());
                    else if (!Strings.isBlank(inherit.getInheritId())) {
                        if (superBean == null)
                            superBean = getInheritTask(cc, rc, inherit);
                        if (superBean != null && superBean.getOnClose() != null)
                            task.setOnClose(superBean.getOnClose());
                    }
                }
                // 引用的对象
                if (Strings.isBlank(task.getRefId())) {
                    if (!Strings.isBlank(inherit.getRefId()))
                        task.setRefId(inherit.getRefId());
                    else if (!Strings.isBlank(inherit.getInheritId())) {
                        if (superBean == null)
                            superBean = getInheritTask(cc, rc, inherit);
                        if (superBean != null
                                && !Strings.isBlank(superBean.getRefId()))
                            task.setRefId(superBean.getRefId());
                    }
                }
                return task;
            } else
                throw new EntityNotFoundException(EntityType.TASK.getName(),
                        task.getInheritId());
        } else
            return task;
    }

    /**
     * @param cc
     * @param page
     * @return
     */
    public final static PageBean getInheritPage(CommandContext cc, RecordContext rc, PageBean page) {
        if (!Strings.isBlank(page.getInheritId())) {
            page = page.clone();
            String pageId = page.getInheritId();
            if (pageId.startsWith("$")) {
                pageId = (String) rc.getValue(pageId.substring(1));
                page.setInheritId(pageId);
            }
            if (Strings.isBlank(pageId))
                return page;
            PageBean inherit = cc.getEntity(pageId);
            if (inherit != null) {
                page = page.clone();
                // load
                if (page.getOnLoad() == null) {
                    if (inherit.getOnLoad() != null)
                        page.setOnLoad(inherit.getOnLoad());
                    else if (!Strings.isBlank(inherit.getInheritId())) {
                        PageBean pb = getInheritPage(cc, rc, inherit);
                        if (pb.getOnLoad() != null)
                            page.setOnLoad(pb.getOnLoad());
                    }
                }
                // refresh
                if (page.getOnRefresh() == null) {
                    if (inherit.getOnRefresh() != null)
                        page.setOnRefresh(inherit.getOnRefresh());
                    else if (!Strings.isBlank(inherit.getInheritId())) {
                        PageBean pb = getInheritPage(cc, rc, inherit);
                        if (pb.getOnRefresh() != null)
                            page.setOnRefresh(pb.getOnRefresh());
                    }
                }
                // ok
                if (page.getOnOk() == null) {
                    if (inherit.getOnOk() != null)
                        page.setOnOk(inherit.getOnOk());
                    else if (!Strings.isBlank(inherit.getInheritId())) {
                        PageBean pb = getInheritPage(cc, rc, inherit);
                        if (pb.getOnOk() != null)
                            page.setOnOk(pb.getOnOk());
                    }
                }
                // back
                if (page.getOnBack() == null) {
                    if (inherit.getOnBack() != null)
                        page.setOnBack(inherit.getOnBack());
                    else if (!Strings.isBlank(inherit.getInheritId())) {
                        PageBean pb = getInheritPage(cc, rc, inherit);
                        if (pb.getOnBack() != null)
                            page.setOnBack(pb.getOnBack());
                    }
                }
                // Table
                if (Strings.isBlank(page.getTable())) {
                    if (!Strings.isBlank(inherit.getTable()))
                        page.setTable(inherit.getTable());
                    else if (!Strings.isBlank(inherit.getTable())) {
                        PageBean pb = getInheritPage(cc, rc, inherit);
                        if (!Strings.isBlank(pb.getTable()))
                            page.setTable(pb.getTable());
                    }
                }
                // 页面显示脚本
                if (Strings.isBlank(page.getOnVisible())) {
                    if (!Strings.isBlank(inherit.getOnVisible()))
                        page.setOnVisible(inherit.getOnVisible());
                    else if (!Strings.isBlank(inherit.getInheritId())) {
                        PageBean pb = getInheritPage(cc, rc, inherit);
                        if (!Strings.isBlank(pb.getOnVisible()))
                            page.setOnVisible(pb.getOnVisible());
                    }
                }
                // 页面脚本
                if (Strings.isBlank(page.getScript())) {
                    if (!Strings.isBlank(inherit.getScript()))
                        page.setScript(inherit.getScript());
                    else if (!Strings.isBlank(inherit.getInheritId())) {
                        PageBean pb = getInheritPage(cc, rc, inherit);
                        if (!Strings.isBlank(pb.getScript()))
                            page.setScript(pb.getScript());
                    }
                }
                // ajax页面
                if (Strings.isBlank(page.getAjax())) {
                    if (!Strings.isBlank(inherit.getAjax()))
                        page.setAjax(inherit.getAjax());
                    else if (!Strings.isBlank(inherit.getInheritId())) {
                        PageBean pb = getInheritPage(cc, rc, inherit);
                        if (!Strings.isBlank(pb.getAjax()))
                            page.setAjax(pb.getAjax());
                    }
                }
                return page;
            } else
                throw new EntityNotFoundException(EntityType.PAGE.getName(),
                        page.getInheritId());
        } else
            return page;
    }

    // TODO
    public final static String getSuperTaskScript(CommandContext cc,
                                                  String name, String inheritId) {
        TaskBean pb = cc.getEntity(inheritId);
        if (pb != null) {
            if (name.equals(ON_INIT)) {
                if (pb.getOnInit().getContent() != null) {
                    return pb.getOnInit().getContent();
                } else if (!Strings.isBlank(pb.getOnInit().getId())) {
                    LogicBean lb = cc.getEntity(pb.getOnInit().getId());
                    if (lb == null)
                        throw new EntityNotFoundException(
                                EntityType.PAGE.getName(), pb.getOnInit().getId());
                    return lb.getContent();
                }
            } else if (name.equals(ON_CLOSE)) {
                if (pb.getOnClose().getContent() != null) {
                    return pb.getOnClose().getContent();
                } else if (!Strings.isBlank(pb.getOnClose().getId())) {
                    LogicBean lb = cc.getEntity(pb.getOnClose().getId());
                    if (lb == null)
                        throw new EntityNotFoundException(
                                EntityType.PAGE.getName(), pb.getOnClose().getId());
                    return lb.getContent();
                }
            } else if (name.equals(ON_PRE_COMMIT)) {
                if (pb.getOnPreCommit().getContent() != null) {
                    return pb.getOnPreCommit().getContent();
                } else if (!Strings.isBlank(pb.getOnPreCommit().getId())) {
                    LogicBean lb = cc.getEntity(pb.getOnPreCommit().getId());
                    if (lb == null)
                        throw new EntityNotFoundException(
                                EntityType.PAGE.getName(), pb.getOnPreCommit().getId());
                    return lb.getContent();
                }
            } else if (name.equals(ON_PRE_COMMIT_ROLLBACK)) {
                if (pb.getOnPreCommitRollback().getContent() != null) {
                    return pb.getOnPreCommitRollback().getContent();
                } else if (!Strings.isBlank(pb.getOnPreCommitRollback().getId())) {
                    LogicBean lb = cc.getEntity(pb.getOnPreCommitRollback().getId());
                    if (lb == null)
                        throw new EntityNotFoundException(
                                EntityType.PAGE.getName(), pb.getOnPreCommitRollback().getId());
                    return lb.getContent();
                }
            } else if (name.equals(ON_BEFORE_COMMIT)) {
                if (pb.getOnBeforeCommit().getContent() != null) {
                    return pb.getOnBeforeCommit().getContent();
                } else if (!Strings.isBlank(pb.getOnBeforeCommit().getId())) {
                    LogicBean lb = cc.getEntity(pb.getOnBeforeCommit().getId());
                    if (lb == null)
                        throw new EntityNotFoundException(
                                EntityType.PAGE.getName(), pb.getOnBeforeCommit().getId());
                    return lb.getContent();
                }
            } else if (name.equals(ON_AFTER_COMMIT)) {
                if (pb.getOnAfterCommit().getContent() != null) {
                    return pb.getOnAfterCommit().getContent();
                } else if (!Strings.isBlank(pb.getOnAfterCommit().getId())) {
                    LogicBean lb = cc.getEntity(pb.getOnAfterCommit().getId());
                    if (lb == null)
                        throw new EntityNotFoundException(
                                EntityType.PAGE.getName(), pb.getOnAfterCommit().getId());
                    return lb.getContent();
                }
            } else if (name.equals(ON_ROLLBACK)) {
                if (pb.getOnRollback().getContent() != null) {
                    return pb.getOnRollback().getContent();
                } else if (!Strings.isBlank(pb.getOnRollback().getId())) {
                    LogicBean lb = cc.getEntity(pb.getOnRollback().getId());
                    if (lb == null)
                        throw new EntityNotFoundException(
                                EntityType.PAGE.getName(), pb.getOnRollback().getId());
                    return lb.getContent();
                }
            } else if (name.equals(ON_COMMITTED)) {
                if (pb.getOnCommitted().getContent() != null) {
                    return pb.getOnCommitted().getContent();
                } else if (!Strings.isBlank(pb.getOnCommitted().getId())) {
                    LogicBean lb = cc.getEntity(pb.getOnCommitted().getId());
                    if (lb == null)
                        throw new EntityNotFoundException(
                                EntityType.PAGE.getName(), pb.getOnCommitted().getId());
                    return lb.getContent();
                }
            } else if (name.equals(ON_COMMITTED_ROLLBACK)) {
                if (pb.getOnCommittedRollback().getContent() != null) {
                    return pb.getOnCommittedRollback().getContent();
                } else if (!Strings.isBlank(pb.getOnCommittedRollback().getId())) {
                    LogicBean lb = cc.getEntity(pb.getOnCommittedRollback().getId());
                    if (lb == null)
                        throw new EntityNotFoundException(
                                EntityType.PAGE.getName(), pb.getOnCommittedRollback().getId());
                    return lb.getContent();
                }
            }
        }
        return "";
    }

    /**
     * @param cc
     * @param name
     * @param inheritId
     * @return
     */
    public final static String getSuperPageScript(CommandContext cc,
                                                  String name, String inheritId) {
        PageBean pb = cc.getEntity(inheritId);
        if (pb != null) {
            if (name.equals(ON_REFRESH)) {
                if (pb.getOnRefresh().getContent() != null) {
                    return pb.getOnRefresh().getContent();
                } else if (!Strings.isBlank(pb.getOnRefresh().getId())) {
                    LogicBean lb = cc.getEntity(pb.getOnRefresh().getId());
                    if (lb == null)
                        throw new EntityNotFoundException(
                                EntityType.PAGE.getName(), pb.getOnRefresh().getId());
                    return lb.getContent();
                }
            } else if (name.equals(ON_OK)) {
                if (pb.getOnOk().getContent() != null) {
                    return pb.getOnOk().getContent();
                } else if (!Strings.isBlank(pb.getOnOk().getId())) {
                    LogicBean lb = cc.getEntity(pb.getOnOk().getId());
                    if (lb == null)
                        throw new EntityNotFoundException(
                                EntityType.PAGE.getName(), pb.getOnOk().getId());
                    return lb.getContent();
                }
            } else if (name.equals(ON_LOAD)) {
                if (pb.getOnLoad().getContent() != null) {
                    return pb.getOnLoad().getContent();
                } else if (!Strings.isBlank(pb.getOnLoad().getId())) {
                    LogicBean lb = cc.getEntity(pb.getOnLoad().getId());
                    if (lb == null)
                        throw new EntityNotFoundException(
                                EntityType.PAGE.getName(), pb.getOnLoad().getId());
                    return lb.getContent();
                }
            } else {
                if (pb.getOnBack().getContent() != null) {
                    return pb.getOnBack().getContent();
                } else if (!Strings.isBlank(pb.getOnBack().getId())) {
                    LogicBean lb = cc.getEntity(pb.getOnBack().getId());
                    if (lb == null)
                        throw new EntityNotFoundException(
                                EntityType.PAGE.getName(), pb.getOnBack().getId());
                    return lb.getContent();
                }
            }
        } else
            throw new EntityNotFoundException(
                    EntityType.PAGE.getName(), inheritId);
        return "";
    }

    public final static String parsePage(CommandContext cc, String page, UserDo user) {
        StringBuilder sb = new StringBuilder();
        char[] cs = page.toCharArray();
        int len = cs.length;
        StringBuilder tmp = new StringBuilder();
        Map<String, String> resources = null;
        Map<String, Object> params = new HashMap<String, Object>();
        RuntimeUtils.initWorkflow(params, null);
        if (user != null && cc.getUser() == null)
            RuntimeUtils.initUser(params, user);
        for (int i = 0; i < len; i++) {
            if (cs[i] == '#' && i < len - 1 && cs[i + 1] == '{') {
                tmp.setLength(0);
                int j = i - 1;
                i += 2;
                while (i < len) {
                    if (cs[i] == '}')
                        break;
                    else
                        tmp.append(cs[i]);
                    i++;
                }
                String name = tmp.toString();
                tmp.setLength(0);
                byte mark = -1;
                for (; j > 0; j--) {
                    if (cs[j] == '"') {
                        while (true) {
                            if (cs[--j] != ' ')
                                break;
                        }
                        mark = 0;
                    }
                    if (mark == 0 && cs[j] == '=') {
                        while (true) {
                            if (cs[--j] != ' ')
                                break;
                        }
                        mark = 1;
                    }
                    if (mark == 1) {
                        tmp.append(cs[j]);
                        if (cs[j] == ' ')
                            break;
                    }
                }
                String attribute = tmp.reverse().toString().trim();
                if (!attribute.equals("id")) {
                    if (name.startsWith("'")) {// i18n#{'xxx'}
                        String code = name.substring(1, name.length() - 1);
                        if (resources == null)
                            resources = cc.getLabels();
                        sb.append(resources.get(code));
                    } else {
                        Object o = params.get(name);
                        if (o != null) {
                            if (o instanceof Date) {
                                String format = cc.getProjectService()
                                        .getConfig().getDateFormat();
                                o = DateFormatUtils.format((Date) o, format);
                            }
                            sb.append(o);
                        }
                    }
                } else
                    sb.append("#{").append(name).append("}");
            } else
                sb.append(cs[i]);
        }
        return sb.toString();
    }

    public final static String parsePage(CommandContext cc, String page) {
        return parsePage(cc, page, null);
    }

    public final static EntityInfo vo2Entity(Object obj) {
        if (obj instanceof ResourceVo) {
            ResourceVo vo = (ResourceVo) obj;
            ResourceBean rb = new ResourceBean();
            rb.setProps(vo.getProps());
            StringBuilder sb = new StringBuilder();
            StringOutputStream os = new StringOutputStream(sb);
            TransformerFactory.newInstance().transformToXml(rb, os);
            EntityInfo entity = new EntityInfo();
            entity.setId(vo.getId());
            entity.setName(vo.getName());
            entity.setType(vo.getType());
            entity.setSubType(vo.getSubType());
            entity.setContent(sb.toString());
            sb = null;
            return entity;
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public final static <T> T cast(Object obj) {
        if (obj instanceof ResourceVo) {
            ResourceVo vo = (ResourceVo) obj;
            ResourceBean rb = new ResourceBean();
            rb.setName(vo.getName());
            rb.setId(vo.getId());
            rb.setSubType(vo.getSubType());
            rb.setProps(vo.getProps());
            return (T) rb;
        } else if (obj instanceof PortletVo) {
            PortletVo pv = (PortletVo) obj;
            PortletBean pb = new PortletBean();
            pb.setName(pv.getName());
            pb.setDesp(pv.getDesp());
            pb.setOnInitQuery(pv.getOnInitQuery());
            pb.setDevices(new ArrayList<>());
            for (DeviceMapVo dv : pv.getDevices()) {
                DeviceMapBean dm = new DeviceMapBean();
                dm.setLoginPage(dv.getLoginPage());
                dm.setMainPage(dv.getMainPage());
                dm.setType(dv.getType());
                dm.setName(dv.getName());
                dm.setTheme(dv.getTheme());
                pb.getDevices().add(dm);
            }
            return (T) pb;
        }
        return null;
    }

    public final static Object cast(ProjectBean pb, String type) {
        if ("template".equals(type)) {
            List<DeviceMapVo> dms = new ArrayList<DeviceMapVo>();
            for (DeviceMapBean mb : pb.getDevices()) {
                DeviceMapVo dm = new DeviceMapVo();
                dm.setLoginPage(mb.getLoginPage());
                dm.setMainPage(mb.getMainPage());
                dm.setName(mb.getName());
                dm.setType(mb.getType());
                dm.setTheme(mb.getTheme());
                dms.add(dm);
            }
            TemplateVo tv = new TemplateVo();
            if (pb.getPortlets() != null && !pb.getPortlets().isEmpty()) {
                List<PortletVo> pvs = new ArrayList<>(pb.getPortlets().size());
                for (PortletBean bean : pb.getPortlets()) {
                    PortletVo vo = new PortletVo();
                    vo.setDesp(bean.getDesp());
                    vo.setName(bean.getName());
                    vo.setOnInitQuery(bean.getOnInitQuery());
                    if (bean.getDevices() != null) {
                        List<DeviceMapVo> devices = new ArrayList<>(bean.getDevices().size());
                        for (DeviceMapBean mb : bean.getDevices()) {
                            DeviceMapVo dm = new DeviceMapVo();
                            dm.setLoginPage(mb.getLoginPage());
                            dm.setMainPage(mb.getMainPage());
                            dm.setName(mb.getName());
                            dm.setType(mb.getType());
                            dm.setTheme(mb.getTheme());
                            devices.add(dm);
                        }
                        vo.setDevices(devices);
                    }
                    pvs.add(vo);
                }
                tv.setPortlets(pvs);
            }
            tv.setDevices(dms);
            return tv;
        } else if ("properties".equals(type))
            return new HashMap<>(pb.getProperties());
        else if ("commands".equals(type)) {//自定义函数
            CustomVo cv = new CustomVo(1);
            if (pb.getCommands() != null) {
                for (CommandBean cmd : pb.getCommands())
                    cv.addEntry(new CustomVo.Entry(cmd.getName(), cmd.getClassName(), cmd.getDescription()));
            }
            return cv;
        } else if ("services".equals(type)) {//自定义服务
            CustomVo cv = new CustomVo(2);
            if (pb.getServices() != null) {
                for (ServiceBean sb : pb.getServices())
                    cv.addEntry(new CustomVo.Entry(sb.getClassName(), sb.getDescription()));
            }
            return cv;
        }
        return null;
    }

    public final static <T extends BaseEntity> Object entity2Vo(T entity) {
        if (entity instanceof TableBean) {
            TableBean tb = (TableBean) entity;
            TableVo tv = new TableVo();
            tv.setId(tb.getId());
            tv.setName(tb.getName());
            for (TableField field : tb.getFields())
                tv.addField(new TableFieldVo(field.getName(), field
                        .getDescription(), field.getType()));
            if (tb.getKey() != null && !tb.getKey().isEmpty()) {
                for (String name : tb.getKey())
                    tv.addKey(name);
            }
            return tv;
        } else if (entity instanceof ProjectBean) {
            ProjectBean pb = (ProjectBean) entity;
            ProjectVo pv = new ProjectVo(pb.getId());
            pv.setAppContext(pb.getAppContext());
            pv.setBizDb(pb.getBizDb());
            pv.setEntityTableName(pb.getEntityTableName());
            pv.setIdentityDb(pb.getIdentityDb());
            pv.setLanguages(pb.getLanguages());
            pv.setMode(pb.getMode());
            pv.setName(pb.getName());
            pv.setDesp(pb.getDescription());
            pv.setProperties(new HashMap<>(pb.getProperties()));
            pv.setTheme(pb.getTheme());
            return pv;
        } else if (entity instanceof PageBean) {
            return ((PageBean) entity).getAjax();
        } else if (entity instanceof ResourceBean) {
            ResourceBean rb = (ResourceBean) entity;
            ResourceVo vo = new ResourceVo(rb.getId(), rb.getName(),
                    new HashMap<>(rb.getProps()));
            vo.setType(rb.getType());
            vo.setSubType(rb.getSubType());
            return vo;
        } else if (entity instanceof LogicBean) {//逻辑直接返回内容
            LogicBean lb = (LogicBean) entity;
            return lb.getContent();
        } else if (entity instanceof ApiBean) {
            ApiBean ab = (ApiBean) entity;
            ApiVo av = new ApiVo();
            av.setId(ab.getId());
            av.setName(ab.getName());
            av.setRefId(ab.getRefId());
            av.setDesp(ab.getDescription());
            av.setRunAsNodes(ab.getRunAsNodes());
            av.setRunAsRoles(ab.getRunAsRoles());
            av.setRunAsUsers(ab.getRunAsUsers());
            av.setAnonymous(ab.isAnonymous());
            if (ab.getInputs() != null && !ab.getInputs().isEmpty()) {
                List<InputVo> inputs = new ArrayList<>(ab.getInputs().size());
                for (Input input : ab.getInputs())
                    inputs.add(new InputVo(input.getName(), input.getDesp(), input.getType(), input.getLength(), input.getDecimal(), input.isRequired()));
                av.setInputs(inputs);
            }
            if (ab.getOutputs() != null && !ab.getOutputs().isEmpty()) {
                StringBuilder sb = new StringBuilder();
                for (Output output : ab.getOutputs())
                    sb.append(output.getName()).append("(").append(output.getDesp()).append(")").append(",");
                sb.deleteCharAt(sb.length() - 1);
                av.setOutputs(sb.toString());
                sb = null;
            }
            return av;
        } else if (entity instanceof EntityInfo) {
            EntityInfo ei = (EntityInfo) entity;
            EntityVo ev = new EntityVo();
            ev.setId(ei.getId());
            ev.setName(ei.getName());
            ev.setDesp(ei.getDescription());
            ev.setContent(ei.getContent());
            return ev;
        }
        return null;
    }
}
